import { Injectable, OnModuleDestroy, OnModuleInit } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import Redis from "ioredis";
// @ts-ignore
import * as redisConfig from "../../redis.config";
import { environmentConfig } from "../config/environment.config";

@Injectable()
export class RedisService implements OnModuleInit, OnModuleDestroy {
  private redis: Redis;

  constructor(private configService: ConfigService) {
    // 使用配置文件，环境变量优先级更高
    const config = {
      host: this.configService.get("REDIS_HOST") || redisConfig.connection.host,
      port:
        parseInt(this.configService.get("REDIS_PORT") || "0") ||
        redisConfig.connection.port,
      password:
        this.configService.get("REDIS_PASSWORD") ||
        redisConfig.connection.password,
      db:
        parseInt(this.configService.get("REDIS_DB") || "0") ||
        redisConfig.connection.db,
      ...redisConfig.options,
    };

    // 验证配置
    try {
      redisConfig.validate();
      redisConfig.printConfig();
    } catch (error: any) {
      console.warn("⚠️ Redis配置验证警告:", error.message);
    }

    this.redis = new Redis(config);

    // 监听连接事件
    this.redis.on("connect", () => {
      console.log("Redis connected successfully");
    });

    this.redis.on("error", (error) => {
      console.error("Redis connection error:", error);
    });

    this.redis.on("ready", () => {
      console.log("Redis is ready");
    });
  }

  async onModuleInit() {
    try {
      // 测试连接
      await this.redis.ping();
      console.log("Redis connection test successful");
    } catch (error) {
      console.error("Redis connection test failed:", error);
    }
  }

  async onModuleDestroy() {
    if (this.redis) {
      await this.redis.quit();
      console.log("Redis connection closed");
    }
  }

  // 获取Redis实例
  getClient(): Redis {
    return this.redis;
  }

  // 设置键值对
  async set(key: string, value: string, ttl?: number): Promise<"OK"> {
    if (ttl) {
      return await this.redis.setex(key, ttl, value);
    }
    return await this.redis.set(key, value);
  }

  // 获取值
  async get(key: string): Promise<string | null> {
    return await this.redis.get(key);
  }

  // 删除键
  async del(key: string): Promise<number> {
    return await this.redis.del(key);
  }

  // 检查键是否存在
  async exists(key: string): Promise<number> {
    return await this.redis.exists(key);
  }

  // 设置过期时间
  async expire(key: string, seconds: number): Promise<number> {
    return await this.redis.expire(key, seconds);
  }

  // 获取剩余过期时间
  async ttl(key: string): Promise<number> {
    return await this.redis.ttl(key);
  }

  // 哈希表操作
  async hset(key: string, field: string, value: string): Promise<number> {
    return await this.redis.hset(key, field, value);
  }

  async hget(key: string, field: string): Promise<string | null> {
    return await this.redis.hget(key, field);
  }

  async hgetall(key: string): Promise<Record<string, string>> {
    return await this.redis.hgetall(key);
  }

  async hdel(key: string, field: string): Promise<number> {
    return await this.redis.hdel(key, field);
  }

  // 列表操作
  async lpush(key: string, value: string): Promise<number> {
    return await this.redis.lpush(key, value);
  }

  async rpush(key: string, value: string): Promise<number> {
    return await this.redis.rpush(key, value);
  }

  async lpop(key: string): Promise<string | null> {
    return await this.redis.lpop(key);
  }

  async rpop(key: string): Promise<string | null> {
    return await this.redis.rpop(key);
  }

  async lrange(key: string, start: number, stop: number): Promise<string[]> {
    return await this.redis.lrange(key, start, stop);
  }

  // 集合操作
  async sadd(key: string, member: string): Promise<number> {
    return await this.redis.sadd(key, member);
  }

  async srem(key: string, member: string): Promise<number> {
    return await this.redis.srem(key, member);
  }

  async smembers(key: string): Promise<string[]> {
    return await this.redis.smembers(key);
  }

  async sismember(key: string, member: string): Promise<number> {
    return await this.redis.sismember(key, member);
  }

  // 有序集合操作
  async zadd(key: string, score: number, member: string): Promise<number> {
    return await this.redis.zadd(key, score, member);
  }

  async zscore(key: string, member: string): Promise<string | null> {
    return await this.redis.zscore(key, member);
  }

  async zrange(key: string, start: number, stop: number): Promise<string[]> {
    return await this.redis.zrange(key, start, stop);
  }

  async zrevrange(key: string, start: number, stop: number): Promise<string[]> {
    return await this.redis.zrevrange(key, start, stop);
  }

  async zrem(key: string, member: string): Promise<number> {
    return await this.redis.zrem(key, member);
  }

  // 发布订阅
  async publish(channel: string, message: string): Promise<number> {
    return await this.redis.publish(channel, message);
  }

  async subscribe(
    channel: string,
    callback: (message: string) => void
  ): Promise<void> {
    const subscriber = new Redis({
      host: this.configService.get("REDIS_HOST", environmentConfig.redis.host),
      port: this.configService.get("REDIS_PORT", environmentConfig.redis.port),
      password: this.configService.get("REDIS_PASSWORD", environmentConfig.redis.password),
      db: this.configService.get("REDIS_DB", environmentConfig.redis.db),
    });

    await subscriber.subscribe(channel);
    subscriber.on("message", (ch, message) => {
      if (ch === channel) {
        callback(message);
      }
    });
  }

  // 测试连接
  async ping(): Promise<string> {
    return await this.redis.ping();
  }

  // 获取Redis信息
  async info(): Promise<string> {
    return await this.redis.info();
  }

  // 清空当前数据库
  async flushdb(): Promise<"OK"> {
    return await this.redis.flushdb();
  }

  // 获取所有键
  async keys(pattern: string): Promise<string[]> {
    return await this.redis.keys(pattern);
  }

  // 获取数据库大小
  async dbsize(): Promise<number> {
    return await this.redis.dbsize();
  }
}
